/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package groupchat;

import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.Method;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.xeerkat.agent.AgentContext;
import org.xeerkat.agent.GroupChat;
import org.xeerkat.agent.Task;
import org.xeerkat.agent.services.ServiceMetadata;
import org.xeerkat.xmpp.ID;

/**
 *
 * @author alex
 */
@ServiceMetadata(id="http://www.xeerkat.org/Service/Test/ParticipantChat/1/0",vendor="xeerkat.org",copyright="2010 xeerkat.org")
public class ParticipantChatApplication extends Application {

   static CountDownLatch LATCH = new CountDownLatch(1);
   static CountDownLatch CONVERSATION = new CountDownLatch(1);
   static AtomicBoolean SUCCESS = new AtomicBoolean(true);
   
   AgentContext agentContext;
   ID chatId;
   GroupChat chat;
   public ParticipantChatApplication(Context context) {
      super(context);
   }

   public Restlet createInboundRoot() {
      return new Restlet(getContext()) {
         public void handle(Request request, Response response) {
            getLogger().info(agentContext.getIdentity()+" MESSAGE: "+request.getEntityAsText());
            response.setStatus(Status.SUCCESS_NO_CONTENT);
         }
      };
   }

   public void start() 
      throws Exception
   {
      boolean started = isStarted();
      super.start();
      if (started) {
         return;
      }
      if (LATCH.getCount()==0) {
         return;
      }

      agentContext = (AgentContext)getContext().getAttributes().get(AgentContext.AGENT_CONTEXT_ATTR);
      chatId = new ID(getContext().getParameters().getFirstValue("conference")+"/"+agentContext.getIdentity().getName());

      getLogger().info(agentContext.getIdentity()+" for "+chatId);

      Task test = agentContext.getTaskManager().create(new Runnable() {
         public void run() {

            try {
               if (!OwnerChatApplication.CREATED.await(15,TimeUnit.SECONDS)) {
                  getLogger().info("Chat room was not created.");
                  SUCCESS.set(false);
                  LATCH.countDown();
                  return;
               }
            } catch (InterruptedException ex) {
               ex.printStackTrace();
               SUCCESS.set(false);
               LATCH.countDown();
               return;
            }
            getLogger().info(agentContext.getIdentity()+" is attempting to join chat "+chatId);
            try {
               chat = agentContext.joinChat(chatId, getContext().getParameters().getFirstValue("password"), new GroupChat.Listener() {

                  public void onCreateFailed(int code, String reason) {
                     getLogger().severe(agentContext.getIdentity()+" Error ("+code+"): "+reason);
                     SUCCESS.set(false);
                     LATCH.countDown();
                  }

                  public void onJoinFailed(int code, String reason) {
                     getLogger().severe(agentContext.getIdentity()+" Cannot join room ("+code+"): "+reason);
                     SUCCESS.set(false);
                     LATCH.countDown();
                  }

                  public void onReady() {
                     getLogger().info(agentContext.getIdentity()+" Room ready, role="+chat.getRole()+", affiliation="+chat.getAffiliation());
                     Task conversation = agentContext.getTaskManager().create(new Runnable() {
                        public void run() {
                           try {
                              Iterator<ID> members = chat.getMembers();
                              while (members.hasNext()) {
                                 getLogger().info(agentContext.getIdentity()+" member: "+members.next());
                              }
                              if (!message("Hi buddy")) {
                                 finish();
                                 return;
                              }
                              if (!message("I+am+fine")) {
                                 finish();
                                 return;
                              }
                              if (!message("goodbye!")) {
                                 finish();
                                 return;
                              }
                              CONVERSATION.countDown();
                              finish();
                           } catch (Exception ex) {
                              ex.printStackTrace();
                           }
                        }
                        void finish() {
                           chat.leave();
                           LATCH.countDown();
                        }
                     });
                     agentContext.getTaskManager().run(conversation);
                  }

                  public void onJoin(ID id) {
                     getLogger().info(agentContext.getIdentity()+" joined: "+id);
                  }

                  public void onLeave(ID id) {
                     getLogger().info(agentContext.getIdentity()+" left: "+id);
                  }

                  public void onDecline(ID id, String reason) {
                     getLogger().info(agentContext.getIdentity()+" declined: "+id+", "+reason);
                  }

               });
            } catch (Exception ex) {
               getLogger().log(Level.SEVERE,"Cannot join chat.",ex);
               SUCCESS.set(false);
            }
         }
      });
      agentContext.getTaskManager().run(test);
   }

   boolean message(String text) {
      Request message = agentContext.createRequest(Method.POST,new Reference("xmpp:"+chat.getRoom()+"?message;type=groupchat&body="+text));
      Response response = getContext().getClientDispatcher().handle(message);
      if (!response.getStatus().isSuccess()) {
         getLogger().severe("XMPP request failed ("+response.getStatus().getCode()+") "+response.getEntityAsText());
         SUCCESS.set(false);
         return false;
      }
      return true;
   }
}
